﻿using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Security.Cryptography;

namespace Hero.Jwt
{
    public class Jwt : IJwt
    {
        private readonly JwtConfig _jwtConfig = new JwtConfig();
        private byte[] signingKey;
        private byte[] encKey=new byte[32];
        public Jwt(IConfiguration configration)
        {
            configration.GetSection("Jwt").Bind(_jwtConfig);
            GenrateSigningKey();
        }
        /// <summary>
        /// 生成签名
        /// 需要用到512位固定长度签名,所以这里用签名算法做是最为稳妥的.
        /// </summary>
        private void GenrateSigningKey()
        {
            System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
            byte[] keyByte = encoding.GetBytes(_jwtConfig.SecretKey);
            byte[] messageBytes = encoding.GetBytes(_jwtConfig.SecretKey);
            using (HMACSHA512 hmacsha512 = new HMACSHA512(keyByte))
            {
                signingKey = hmacsha512.ComputeHash(messageBytes);
                Buffer.BlockCopy(signingKey, 10, encKey, 0, encKey.Length);
            }
        }
        /// <summary>
        /// 生成Token
        /// </summary>
        /// <param name="Claims"></param>
        /// <returns></returns>
        public string GetToken(IDictionary<string, object> Claims)
        {
            string pubkeySigning = "MIIBCgKCAQEAuyeviRRcsPGxSUyYnhE8zYFquUc4InAa5K4qw5Y43R/1sm5jWZiG670+aq+y/1Ovx4RXlyBpzwo4ws0FB7YZyPIPRiZZbB9oIeNd19fdPu7U70lSaIfh9TjHW9Kjb40YFnxm6nltY7QXTw2VeISVZApD0DcL8TieD3cgGpKJjo4nhaHNFmRLR80mSOjFrKFoun5iLk1azljHEpVjqVotKF+5o80DzxW7EywoS2YuXYMI7tOIPP33cRLMFxokZSy2BFeeuu4jakDsvTxMaipOCyumbE2/Fd7bo59n1/jgfyP11rR8HtkhdS9SbK0nw6rVEddFxym6TKjczrxIYxuR4QIDAQAB";
            string prikeySigning = "MIIEogIBAAKCAQEAuyeviRRcsPGxSUyYnhE8zYFquUc4InAa5K4qw5Y43R/1sm5jWZiG670+aq+y/1Ovx4RXlyBpzwo4ws0FB7YZyPIPRiZZbB9oIeNd19fdPu7U70lSaIfh9TjHW9Kjb40YFnxm6nltY7QXTw2VeISVZApD0DcL8TieD3cgGpKJjo4nhaHNFmRLR80mSOjFrKFoun5iLk1azljHEpVjqVotKF+5o80DzxW7EywoS2YuXYMI7tOIPP33cRLMFxokZSy2BFeeuu4jakDsvTxMaipOCyumbE2/Fd7bo59n1/jgfyP11rR8HtkhdS9SbK0nw6rVEddFxym6TKjczrxIYxuR4QIDAQABAoIBAHAnCwjhW95pJ61eKkLm34HjIPpglGIGvgb13AiS+AaCxXCkuAKT5Z5VLJcwLNrW4op0YyzcLqv0WylZRL9nP7JsY/zMtF+XvoY4Qx86a4nwA0hVrv2XGDAkU0tSQcByU9H9wIqYM5ZA8IreAAlVolRt1k9q/UwTepyX7XQfBjGXNft0qu3A3gLIpzVn/oH5mD4UNsNDdgJ/s4FebvdGSucM/UWBoDP4TaotN1IV8yBNyFJhBWMkbRLs20dbfgiFqDnRF8+69Ylw6qrokHDZwZRB5/NMiFt+UFmCFc3RbSps2L1tWLOdAQ5MPTELn+1kk26jkcHP7cZXVbOzqHKQkTUCgYEA2LkujXIdOY1LeB5bSkPUND8PtmVgrsiAEfP/nWX629+UIqwwGtGJz9Gt5c3CNvIsGzazHaUE4DI5ru4B+HgU45ifbLMtII5AtdY8oPd0nTwHpF6iSYKmJzPFPdordyxZ36CLzhaVI9mdHRJS84Fj5O1DJ548PANLz5rTLDiJEbsCgYEA3RKwY636eo3sIjHVHTe3gOt+s3Q41P+Lh1v9TiEuZthg3f7tZUY2EQileLxNAjgAK48XMbtgRTLNax688WjjLIQaYQyXl074gJ1Hn/dirNOGQMrYgrxXmM5oBgXqmEA321W9hz9k7JRYw7HqjKSL2+h8GeacXfkFyC9YZiFFMxMCgYBdNhBSn6D4LtAlwpCq+U9chT7hyOpzYiLLFfF7pe/l/1w8KWirMDIgouMzMnL0pOXZcoZJGr9lGdT7aryIPEVnui3fV5TyKpykWJdM+AE82yPCSz1rdni15atQtfP51qZ06x0WL1pHyAGuDkKFHsJzJKS8dm8btKM3kDSBEXPKnwKBgG8bt39Br4Ps1GMTPJLkr9uhgBpdLTsP/GZZe2PLFXEnCvhH6bRep0nEWLXnnaSh1KQP1I5wKCBfOhK+biO+nX6AHmnsVDv9urOZWKgzQ2qtHOpviIWcd0Ibavir/I3sqKYZ35mb6PNmU353avSotoodvFGgL7KjN562/OzHh+n1AoGAFBFnvge50H2FTT2MlKZ53yY27OAuKK2+KUQGK8OIP4fSWvisFzA68cQrejyAxkx4JMMic0OnHgLMi75Noz6aUYDdtRmuzkmxugz96bhFuj1UhH3HqqaLwn8yrw68X4dUD6eSv7sBhL9RJTVz3cuaR1wFaXZfEhfVcdRlvDYfa0k=";
            string pubkeyEncrypt = "MIIBCgKCAQEAxKrM4LqoQ7O37Wiybx/80NUwi9dDc+hP5MWx/uAyaoWsCTE3AXTcANqKR4MWd8FDKpyJn9WrIDaRnl4XuW8992Bpzqo4KbHlefQ6z848ox7M8BCqyiQ0uz5FeezFzhe1FBGpRmw1o1rH3mpjnkjpb81wWY6NyI6k7/ZUIQFX5Sn8g4vnaGNBlnhhd3oh8esM2IhoDcPvK2QXnpCa1o+md7O3VM1J1M2jIVvULaE5dxz2NIUCQnxFCgH/XYKfcEZEwjBubkFK2HP+pPKo0ZX9kfQ2MPOj7l04YTikA2Majym3BL38U/bNSt8rYHg5EIWwwObYxlo6NOWQRFYM9c1fZQIDAQAB";
            string prikeyEncrypt = "MIIEpAIBAAKCAQEAxKrM4LqoQ7O37Wiybx/80NUwi9dDc+hP5MWx/uAyaoWsCTE3AXTcANqKR4MWd8FDKpyJn9WrIDaRnl4XuW8992Bpzqo4KbHlefQ6z848ox7M8BCqyiQ0uz5FeezFzhe1FBGpRmw1o1rH3mpjnkjpb81wWY6NyI6k7/ZUIQFX5Sn8g4vnaGNBlnhhd3oh8esM2IhoDcPvK2QXnpCa1o+md7O3VM1J1M2jIVvULaE5dxz2NIUCQnxFCgH/XYKfcEZEwjBubkFK2HP+pPKo0ZX9kfQ2MPOj7l04YTikA2Majym3BL38U/bNSt8rYHg5EIWwwObYxlo6NOWQRFYM9c1fZQIDAQABAoIBACr8vn2cryzlOp3NFbuOfV9USiE280qBi/0QbWCttrdr8ner5z8NQQ16t2D8OUwB1WGaB8cFGDuZUekQ3hStSRkqXNZMhKwwc11d0gEcLkrlb5xFuF8o3NHUwbDt3Sq4Kd9yINMA0hSbwjZOgOnXPBcxC463xywAafL9n9P7DDBNw17l2ykW7gJtNRy6tf2kjCEfnHEIgXZZ19xp/BfApYAcLb/v9C/tRaWAzWLLTwX9GEOrJ2XjzIUOrdCmdO85VbH3b2bGHWwi2orbD+uvCZOPcCsOyQjUme40JaDQwgkCPTh/9F5/u/Z8sVcCw/mgzoaxWImdCwwQCj49FhT52V0CgYEA/CEL1VlL5Gb2tolhG8hufORzu2Id0uDNKsUZd92hM4Y98tyDnCqE/F3jiv63G0utHSzC3Rt77iiX9LXXV3AP/Zz91LNEm/vICSEeDOFejx7XEsnjsJuoDMZPt+bNu4bFWv0j81fuVyZ9ZPoy4xb+abmkebq9F2QxvcQs2DO+SKMCgYEAx6/FEaGKk10XWCdFEBeI3I3GViDYzSBEEnaI+wSR7VPBZkCt0w2aD4/wrw3pmlTAkN882GDdFzojtEd7t2nXgp03S0F5T5aGD4pFZWaqUYqz/bQ/UxBp0C5qHR084J5XarllTPBzbZ0fo1eY1Cde/mj/TD722o+9hUsmbi0NkFcCgYEAsZRY8FCvmlRG6jQCeH4IC+Ef/lfR56g7+SbPlFQ+aLrhQP+9lq1/8vvx+wECWLBJYqYXLYJhHFHtDQdSf5xHNvpu8XO+HBsPPhbcQngtkKJJG0ulGcvYZf77QOzH9I+syzRGMOu6zBko8okidD3KvQ5q4O38ptAEFMNqTnDLUf8CgYB6k/VfG1DboRuBa6nDdQ74hLcpi8RKNvJSex0fKfECRJXF1RJfKkxWHT/b1ah+qmQDCmZpVRyi83eTZQYW0wwOC8AznB+BsZ7dzz1GP71xjLlslccBkGPD/Zn6AUarg8eZpfD/R+MzeG5BcLZKFVkExyNghI44IGBwgG841sMqxQKBgQD6nSV5kw8RXBlzWfjI/q9hU0f9U4E2ZX66iNrUhlmK12yDXd0l3I4vpffo2HQVHRGP+4LKnX7g+7P6Zrs3GHoOg7EbnYjcReoBNoxwgTx93b6qBEi9yfQNYVPgZIwxMYq62yNlTcAp9CQLAwkOWaTO51viAVICUOmbQelIny9cMA==";
            RSA rsaSigning = RSA.Create();
            //rsaSigning.ExportRSAPrivateKey() 生成私钥
            //rsaSigning.ExportRSAPublicKey() 生成公钥
            rsaSigning.ImportRSAPrivateKey(Convert.FromBase64String(prikeySigning), out int bytesread);
            RSA rsaEncrypt = RSA.Create();
            rsaEncrypt.ImportRSAPublicKey(Convert.FromBase64String(pubkeyEncrypt), out int bytesread1);
            JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
            SecurityTokenDescriptor tokenDescriptor = new SecurityTokenDescriptor
            {
                Issuer = _jwtConfig.Issuer,
                Audience = _jwtConfig.Audience,
                NotBefore = DateTime.Now,
                Expires = DateTime.Now.AddMinutes(_jwtConfig.Lifetime),
                Claims =Claims,
                //SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(signingKey), SecurityAlgorithms.HmacSha512),//对称加密
                //EncryptingCredentials = new EncryptingCredentials(new SymmetricSecurityKey(encKey), SecurityAlgorithms.Aes256KW, SecurityAlgorithms.Aes256CbcHmacSha512)
                SigningCredentials = new SigningCredentials(new RsaSecurityKey(rsaSigning.ExportParameters(true)), SecurityAlgorithms.RsaSsaPssSha512),//非对称私钥签名,公钥验签
                EncryptingCredentials = new EncryptingCredentials(new RsaSecurityKey(rsaEncrypt.ExportParameters(false)), SecurityAlgorithms.RsaOAEP, SecurityAlgorithms.Aes128CbcHmacSha256)//非对称加密
                
            };
            SecurityToken securityToken = tokenHandler.CreateToken(tokenDescriptor);
            return tokenHandler.WriteToken(securityToken);
        }
        public bool ValidateToken(string Token, out Dictionary<string, object> Clims)
        {
            string pubkeySigning = "MIIBCgKCAQEAuyeviRRcsPGxSUyYnhE8zYFquUc4InAa5K4qw5Y43R/1sm5jWZiG670+aq+y/1Ovx4RXlyBpzwo4ws0FB7YZyPIPRiZZbB9oIeNd19fdPu7U70lSaIfh9TjHW9Kjb40YFnxm6nltY7QXTw2VeISVZApD0DcL8TieD3cgGpKJjo4nhaHNFmRLR80mSOjFrKFoun5iLk1azljHEpVjqVotKF+5o80DzxW7EywoS2YuXYMI7tOIPP33cRLMFxokZSy2BFeeuu4jakDsvTxMaipOCyumbE2/Fd7bo59n1/jgfyP11rR8HtkhdS9SbK0nw6rVEddFxym6TKjczrxIYxuR4QIDAQAB";
            string prikeySigning = "MIIEogIBAAKCAQEAuyeviRRcsPGxSUyYnhE8zYFquUc4InAa5K4qw5Y43R/1sm5jWZiG670+aq+y/1Ovx4RXlyBpzwo4ws0FB7YZyPIPRiZZbB9oIeNd19fdPu7U70lSaIfh9TjHW9Kjb40YFnxm6nltY7QXTw2VeISVZApD0DcL8TieD3cgGpKJjo4nhaHNFmRLR80mSOjFrKFoun5iLk1azljHEpVjqVotKF+5o80DzxW7EywoS2YuXYMI7tOIPP33cRLMFxokZSy2BFeeuu4jakDsvTxMaipOCyumbE2/Fd7bo59n1/jgfyP11rR8HtkhdS9SbK0nw6rVEddFxym6TKjczrxIYxuR4QIDAQABAoIBAHAnCwjhW95pJ61eKkLm34HjIPpglGIGvgb13AiS+AaCxXCkuAKT5Z5VLJcwLNrW4op0YyzcLqv0WylZRL9nP7JsY/zMtF+XvoY4Qx86a4nwA0hVrv2XGDAkU0tSQcByU9H9wIqYM5ZA8IreAAlVolRt1k9q/UwTepyX7XQfBjGXNft0qu3A3gLIpzVn/oH5mD4UNsNDdgJ/s4FebvdGSucM/UWBoDP4TaotN1IV8yBNyFJhBWMkbRLs20dbfgiFqDnRF8+69Ylw6qrokHDZwZRB5/NMiFt+UFmCFc3RbSps2L1tWLOdAQ5MPTELn+1kk26jkcHP7cZXVbOzqHKQkTUCgYEA2LkujXIdOY1LeB5bSkPUND8PtmVgrsiAEfP/nWX629+UIqwwGtGJz9Gt5c3CNvIsGzazHaUE4DI5ru4B+HgU45ifbLMtII5AtdY8oPd0nTwHpF6iSYKmJzPFPdordyxZ36CLzhaVI9mdHRJS84Fj5O1DJ548PANLz5rTLDiJEbsCgYEA3RKwY636eo3sIjHVHTe3gOt+s3Q41P+Lh1v9TiEuZthg3f7tZUY2EQileLxNAjgAK48XMbtgRTLNax688WjjLIQaYQyXl074gJ1Hn/dirNOGQMrYgrxXmM5oBgXqmEA321W9hz9k7JRYw7HqjKSL2+h8GeacXfkFyC9YZiFFMxMCgYBdNhBSn6D4LtAlwpCq+U9chT7hyOpzYiLLFfF7pe/l/1w8KWirMDIgouMzMnL0pOXZcoZJGr9lGdT7aryIPEVnui3fV5TyKpykWJdM+AE82yPCSz1rdni15atQtfP51qZ06x0WL1pHyAGuDkKFHsJzJKS8dm8btKM3kDSBEXPKnwKBgG8bt39Br4Ps1GMTPJLkr9uhgBpdLTsP/GZZe2PLFXEnCvhH6bRep0nEWLXnnaSh1KQP1I5wKCBfOhK+biO+nX6AHmnsVDv9urOZWKgzQ2qtHOpviIWcd0Ibavir/I3sqKYZ35mb6PNmU353avSotoodvFGgL7KjN562/OzHh+n1AoGAFBFnvge50H2FTT2MlKZ53yY27OAuKK2+KUQGK8OIP4fSWvisFzA68cQrejyAxkx4JMMic0OnHgLMi75Noz6aUYDdtRmuzkmxugz96bhFuj1UhH3HqqaLwn8yrw68X4dUD6eSv7sBhL9RJTVz3cuaR1wFaXZfEhfVcdRlvDYfa0k=";
            string pubkeyEncrypt = "MIIBCgKCAQEAxKrM4LqoQ7O37Wiybx/80NUwi9dDc+hP5MWx/uAyaoWsCTE3AXTcANqKR4MWd8FDKpyJn9WrIDaRnl4XuW8992Bpzqo4KbHlefQ6z848ox7M8BCqyiQ0uz5FeezFzhe1FBGpRmw1o1rH3mpjnkjpb81wWY6NyI6k7/ZUIQFX5Sn8g4vnaGNBlnhhd3oh8esM2IhoDcPvK2QXnpCa1o+md7O3VM1J1M2jIVvULaE5dxz2NIUCQnxFCgH/XYKfcEZEwjBubkFK2HP+pPKo0ZX9kfQ2MPOj7l04YTikA2Majym3BL38U/bNSt8rYHg5EIWwwObYxlo6NOWQRFYM9c1fZQIDAQAB";
            string prikeyEncrypt = "MIIEpAIBAAKCAQEAxKrM4LqoQ7O37Wiybx/80NUwi9dDc+hP5MWx/uAyaoWsCTE3AXTcANqKR4MWd8FDKpyJn9WrIDaRnl4XuW8992Bpzqo4KbHlefQ6z848ox7M8BCqyiQ0uz5FeezFzhe1FBGpRmw1o1rH3mpjnkjpb81wWY6NyI6k7/ZUIQFX5Sn8g4vnaGNBlnhhd3oh8esM2IhoDcPvK2QXnpCa1o+md7O3VM1J1M2jIVvULaE5dxz2NIUCQnxFCgH/XYKfcEZEwjBubkFK2HP+pPKo0ZX9kfQ2MPOj7l04YTikA2Majym3BL38U/bNSt8rYHg5EIWwwObYxlo6NOWQRFYM9c1fZQIDAQABAoIBACr8vn2cryzlOp3NFbuOfV9USiE280qBi/0QbWCttrdr8ner5z8NQQ16t2D8OUwB1WGaB8cFGDuZUekQ3hStSRkqXNZMhKwwc11d0gEcLkrlb5xFuF8o3NHUwbDt3Sq4Kd9yINMA0hSbwjZOgOnXPBcxC463xywAafL9n9P7DDBNw17l2ykW7gJtNRy6tf2kjCEfnHEIgXZZ19xp/BfApYAcLb/v9C/tRaWAzWLLTwX9GEOrJ2XjzIUOrdCmdO85VbH3b2bGHWwi2orbD+uvCZOPcCsOyQjUme40JaDQwgkCPTh/9F5/u/Z8sVcCw/mgzoaxWImdCwwQCj49FhT52V0CgYEA/CEL1VlL5Gb2tolhG8hufORzu2Id0uDNKsUZd92hM4Y98tyDnCqE/F3jiv63G0utHSzC3Rt77iiX9LXXV3AP/Zz91LNEm/vICSEeDOFejx7XEsnjsJuoDMZPt+bNu4bFWv0j81fuVyZ9ZPoy4xb+abmkebq9F2QxvcQs2DO+SKMCgYEAx6/FEaGKk10XWCdFEBeI3I3GViDYzSBEEnaI+wSR7VPBZkCt0w2aD4/wrw3pmlTAkN882GDdFzojtEd7t2nXgp03S0F5T5aGD4pFZWaqUYqz/bQ/UxBp0C5qHR084J5XarllTPBzbZ0fo1eY1Cde/mj/TD722o+9hUsmbi0NkFcCgYEAsZRY8FCvmlRG6jQCeH4IC+Ef/lfR56g7+SbPlFQ+aLrhQP+9lq1/8vvx+wECWLBJYqYXLYJhHFHtDQdSf5xHNvpu8XO+HBsPPhbcQngtkKJJG0ulGcvYZf77QOzH9I+syzRGMOu6zBko8okidD3KvQ5q4O38ptAEFMNqTnDLUf8CgYB6k/VfG1DboRuBa6nDdQ74hLcpi8RKNvJSex0fKfECRJXF1RJfKkxWHT/b1ah+qmQDCmZpVRyi83eTZQYW0wwOC8AznB+BsZ7dzz1GP71xjLlslccBkGPD/Zn6AUarg8eZpfD/R+MzeG5BcLZKFVkExyNghI44IGBwgG841sMqxQKBgQD6nSV5kw8RXBlzWfjI/q9hU0f9U4E2ZX66iNrUhlmK12yDXd0l3I4vpffo2HQVHRGP+4LKnX7g+7P6Zrs3GHoOg7EbnYjcReoBNoxwgTx93b6qBEi9yfQNYVPgZIwxMYq62yNlTcAp9CQLAwkOWaTO51viAVICUOmbQelIny9cMA==";
            RSA rsaSigning = RSA.Create();
            rsaSigning.ImportRSAPublicKey(Convert.FromBase64String(pubkeySigning), out int bytesread);
            RSA rsaEncrypt = RSA.Create();
            rsaEncrypt.ImportRSAPrivateKey(Convert.FromBase64String(prikeyEncrypt), out int bytesread1);
            Clims = new Dictionary<string, object>();
            ClaimsPrincipal principal = null;
            if (string.IsNullOrWhiteSpace(Token))
            {
                return false;
            }
            JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
            try
            {
                JwtSecurityToken jwt = handler.ReadJwtToken(Token);
                if (jwt == null)
                {
                    return false;
                }
                TokenValidationParameters validationParameters = new TokenValidationParameters
                {
                    RequireExpirationTime = true,
                    ClockSkew = TimeSpan.Zero,
                    //IssuerSigningKey = new SymmetricSecurityKey(signingKey),
                    //TokenDecryptionKey = new SymmetricSecurityKey(encKey),
                    IssuerSigningKey = new RsaSecurityKey(rsaSigning.ExportParameters(false)),//公钥解密 --签名算法
                    TokenDecryptionKey = new RsaSecurityKey(rsaEncrypt.ExportParameters(true)),//私钥解密--解密算法
                    ValidateIssuer = true,//是否验证Issuer
                    ValidateAudience = true,//是否验证Audience
                    ValidateLifetime = _jwtConfig.ValidateLifetime,//是否验证失效时间
                    ValidAudience = _jwtConfig.Audience,
                    ValidIssuer = _jwtConfig.Issuer,
                    ValidateIssuerSigningKey = true,//是否验证签名
                };
                principal = handler.ValidateToken(Token, validationParameters, out SecurityToken securityToken);
                foreach (Claim item in principal.Claims)
                {
                    Clims.Add(item.Type, item.Value);
                }
                return true;
            }
            catch (SecurityTokenInvalidLifetimeException ex)
            {
                Console.WriteLine(ex.Message);
                return false;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return false;
            }
        }
    }
}
